package com.cskaoyan.javase.array._5operation._3crud;

import java.io.PushbackInputStream;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 数组是一个容器，可以用存放元素，存放数据。
 * 在实际开发中，工程中也会需要存放大量数据，这一般是通过数据库来实现的。
 * 实际开发的基本需求就是基于数据库的，对数据进行增删改查，即"crud"
 * 也有很多中低级Java程序员自嘲自己为"crud工程师"。
 *
 * 当然"crud"指的是：
 * c，create：新增数据/增加。
 * r，retrieve：检索数据/查询。
 * u，update：更新数据/修改。
 * d，delete ：删除数据/删除。
 *
 * 我们现在还没有学习过数据库，但是不重要。
 * 现在我们使用数组这个容器，来模拟数据库，实现日常开发中最常见的"crud"操作。
 *
 * 需求:
 *      现在给出一个String数组作为一个容器,该数组用来存储人的名字
 *      并且该容器中的人名必须是唯一的,不存在两个相同的名字
 *      现在要求实现对该容器的增删改查等操作.
 *
 * @since 16:11
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 创建姓名String容器
        String[] names = new String[10];
        names[0] = "张三";
        names[1] = "李四";
        names[2] = "张麻子";
        names[3] = "马化腾";
        names[4] = "师爷";
        printRealNames(names);
        Scanner sc = new Scanner(System.in);
        /*System.out.println("现在开始新增一条姓名信息:");
        System.out.println("请键盘录入一条需要新增的姓名信息:");
        String nameInsert = sc.nextLine();
        switch (createName(names, nameInsert)) {
            case 1:
                System.out.println("新增失败,姓名重复了!");
                printRealNames(names);
                break;
            case 2:
                System.out.println("新增失败,数组满了!");
                printRealNames(names);
                break;
            case 3:
                System.out.println("新增成功了!");
                printRealNames(names);
                break;
        }*/

        /*System.out.println("现在开始删除一条姓名信息:");
        System.out.println("请键盘录入一条需要删除的姓名信息:");
        String nameDelete = sc.nextLine();
        if (deleteName(names, nameDelete)) {
            System.out.println("删除成功!");
            printRealNames(names);
        } else {
            System.out.println("删除失败!没找到目标元素!");
            printRealNames(names);
        }*/

        /*System.out.println("现在开始更新一条姓名信息:");
        System.out.println("请键盘录入一条需要更新的姓名信息:");
        String nameUpdate = sc.nextLine();
        System.out.println("请键盘录入一条需要更新的姓名信息的目标值:");
        String nameNewValue = sc.nextLine();
        if (updateName(names, nameUpdate, nameNewValue)) {
            System.out.println("更新成功!");
            printRealNames(names);
        } else {
            System.out.println("更新失败!没找到目标元素!");
            printRealNames(names);
        }*/

        System.out.println(retrieveName(names, "ls"));

    }

    // 先实现一个需求: 用于打印姓名容器中的元素,只显示真实姓名,不显示null
    public static void printRealNames(String[] names) {
        System.out.println("姓名容器中的真实姓名有:");
        System.out.print("[");
        for (String name : names) {
            // 判断null,因为null元素不打印
            if (name == null) {
                continue;
            }
            System.out.print(name + ", ");
        }
        System.out.println("\b\b]");
    }
    // 增
    /*
        数组是不可能真的去增加一个元素的
        所以这里的增加指的是,找到一个null元素的位置
        然后给它赋值
        所以新增本质上就是赋值
        该方法的返回值,需要用于指示新增操作的成功与否
        分析,新增有以下情况:
            1.新增的姓名已经重复了,新增失败
            2.姓名不重复,但是数组已经满了,新增失败
            3.以上失败情况都不存在,新增成功
       这时存在三种状态需要指出,所以不能用boolean
       可以考虑返回一个状态值,比如:
            1.新增的姓名已经重复了,新增失败,返回状态值1
            2.姓名不重复,但是数组已经满了,新增失败,返回状态值2
            3.新增成功,返回状态3
     */

    /**
     * 1.新增的姓名已经重复了,新增失败,返回状态值1
     * 2.姓名不重复,但是数组已经满了,新增失败,返回状态值2
     * 3.新增成功,返回状态3
     * @param names 被新增元素的姓名数组
     * @param target 被新增的名字
     * @return int
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/05/12 16:25
     */
    public static int createName(String[] names, String target) {
        /*
            从写规范的代码角度出发
            方法需要返回状态值时,如果直接把整数常量作为返回值是不太规范的
            因为在编程规范中,有一个很重要的原则: 不要使用魔法值
            魔法值: 指的是没有任何定义,直接出现在代码中的一个常量
            由于魔法值的出现,会引起不必要的思考,所以不建议使用魔法值
            而是可以预先定义一下.
         */
        int statusValue = 2;
        // 1.先判断是否是已经重复的名字
        // 遍历容器,逐一比较,判断是否重复
        for (String name : names) {
            // if判null是常用的做法
            /*if (name == null){
                continue;
            }*/
            // 考虑对称性,因为target绝无可能为null,所以用它调用方法
            if (target.equals(name)) {
                // 说明重复了
                statusValue = 1;
                return statusValue;
            }
        }
        // 代码能够运行到这里,说明姓名肯定是不重复的
        // 2.如果姓名不是重复的,尝试插入姓名,如果插入不成功,说明数组满了
        for (int i = 0; i < names.length; i++) {
            // 找到一个null的位置,然后赋值
            if (names[i] == null) {
                // 插入成功
                names[i] = target;
                statusValue = 3;
                return statusValue;
            }
        }
        // 遍历完整个数组,都没有插入,说明数组满了
        return statusValue;
    }

    // 删
    /*
        删除指的是将数组中某个姓名字符串,赋值为null
        删除这个方法也需要返回一个状态，指示删除是否成功
        删除的结果,有两种的:
              1.找到了目标姓名,删除成功
              2.没找到,删除失败
     */

    /**
     * 删除成功返回true
     * 删除失败返回false
     * @param names 被删除元素的数组
     * @param target 被删除的元素
     * @return boolean
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/05/12 17:17
     */
    public static boolean deleteName(String[] names, String target) {
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                // 找到了,置为null,删除成功
                names[i] = null;
                return true;
            }
        }
        // 删除失败,没找到元素
        return false;
    }

    // 改

    /**
     * 找到修改成功,返回true
     * 没找到修改失败,返回false
     * @param names 被修改元素的数组
     * @param target 被修改的目标元素
     * @param newValue 修改的目标值
     * @return boolean
     * @author wuguidong@cskaoyan.onaliyun.com
     * @since 2022/05/12 17:23
     */
    public static boolean updateName(String[] names, String target, String newValue) {
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                // 找到了,置为新的取值,更新成功
                names[i] = newValue;
                return true;
            }
        }
        // 更新失败,没找到元素
        return false;
    }

    // 查
    /*
        查找目标元素,然后返回目标元素在数组中的下标
     */
    public static int retrieveName(String[] names, String target) {
        int targetIndex = -1;
        for (int i = 0; i < names.length; i++) {
            if (target.equals(names[i])) {
                // 找到了
                targetIndex = i;
            }
        }
        // 没找到,也许返回一个整数,这时返回一个绝不可能存在的下标,一般都会选择返回-1
        return targetIndex;
    }
}
